package com.ibeeking.found.upms.b.rest.service.impl;

import com.ibeeking.found.upms.b.rest.service.IShopRoleService;
import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.common.constants.RoleConstant;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.upms.service.common.bo.ShopRoleBO;
import com.ibeeking.found.upms.service.common.dos.ShopPermissionDO;
import com.ibeeking.found.upms.service.common.dos.ShopRoleDO;
import com.ibeeking.found.upms.service.common.dos.ShopRolePermissionDO;
import com.ibeeking.found.upms.service.common.param.RolePermissionParam;
import com.ibeeking.found.upms.service.common.param.ShopRoleParam;
import com.ibeeking.found.upms.service.common.query.ShopRolePageQuery;
import com.ibeeking.found.upms.service.common.vo.ShopRolePageVO;
import com.ibeeking.found.upms.service.common.vo.ShopRoleVO;
import com.ibeeking.found.upms.service.mapper.ShopPermissionMapper;
import com.ibeeking.found.upms.service.mapper.ShopRoleMapper;
import com.ibeeking.found.upms.service.mapper.ShopRolePermissionMapper;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName OriginalShopRoleServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-04-15 11:46
 **/
@Service
public class ShopRoleServiceImpl implements IShopRoleService {

    @Resource
    private ShopRoleMapper shopRoleMapper;
    @Resource
    private ShopRolePermissionMapper shopRolePermissionMapper;
    @Resource
    private ShopPermissionMapper shopPermissionMapper;

    @Override
    public Page<ShopRolePageVO> pageList(ShopRolePageQuery query) {
        LambdaQueryWrapper<ShopRoleDO> queryWrapper = new LambdaQueryWrapper<>(ShopRoleDO.class);
        queryWrapper
                .orderByAsc(ShopRoleDO::getSort)
                .orderByDesc(BaseDO::getCreateTime)
                .eq(null != query.getPublishStatus(), ShopRoleDO::getPublishStatus, query.getPublishStatus())
                .eq(StringUtils.isNotBlank(query.getCode()), ShopRoleDO::getCode, query.getCode())
                .like(StringUtils.isNotBlank(query.getName()), ShopRoleDO::getName, query.getName())
        ;
        Page<ShopRoleDO> page = shopRoleMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), queryWrapper);
        return BeanUtil.convertPage(page, ShopRolePageVO.class);
    }

    @Override
    public Boolean add(ShopRoleParam param) {
        ShopRoleDO roleDO = BeanUtil.convertBean(param, ShopRoleDO.class);
        if (!checkUnique(roleDO)) {
            //throw new BusinessException("当前角色编码或名称已存在");
            throw new BusinessException("当前角色名称已存在");
        }
        roleDO.setCode("");
        roleDO.setCreateBy(UserUtils.getUserId());
        roleDO.setCreateTime(LocalDateTime.now());
        roleDO.setModifyTime(LocalDateTime.now());
        return shopRoleMapper.insert(roleDO) > 0;
    }

    @Override
    public Boolean modify(ShopRoleParam param) {
        ShopRoleDO roleDO = BeanUtil.convertBean(param, ShopRoleDO.class);
        if (!checkUnique(roleDO)) {
            //throw new BusinessException("当前角色编码或名称已存在");
            throw new BusinessException("当前角色名称已存在");
        }
        roleDO.setCode(null);
        roleDO.setModifyBy(UserUtils.getUserId());
        roleDO.setModifyTime(LocalDateTime.now());
        return shopRoleMapper.updateById(roleDO) > 0;
    }

    @Override
    public ShopRoleVO view(Long id) {
        ShopRoleBO roleBO = getBean().queryById(id);
        return BeanUtil.convertBean(roleBO, ShopRoleVO.class);
    }

    @Override
    public ShopRoleBO queryById(Long id) {
        ShopRoleDO roleDO = shopRoleMapper.selectById(id);
        return BeanUtil.convertBean(roleDO, ShopRoleBO.class);
    }

    @Override
    public Boolean changeStatus(Long id, Integer status) {
        ShopRoleDO roleDO = new ShopRoleDO();
        roleDO.setId(id);
        roleDO.setPublishStatus(status);
        if (RoleConstant.ADMINISTRATOR.equals(getBean().queryById(id).getCode()) && PublishStatusEnum.DISABLE.getValue().equals(status)) {
            throw new BusinessException("超级管理员不允许禁用");
        }
        roleDO.setModifyBy(UserUtils.getUserId());
        roleDO.setModifyTime(LocalDateTime.now());
        return shopRoleMapper.updateById(roleDO) > 0;
    }

    @Override
    public Boolean del(Long id) {
        ShopRoleBO roleBO = getBean().queryById(id);
        if (null == roleBO) {
            return true;
        }
        if (RoleConstant.ADMINISTRATOR.equals(roleBO.getCode())) {
            throw new BusinessException("超级管理员不允许删除");
        }
        if (PublishStatusEnum.ENABLE.getValue().equals(roleBO.getPublishStatus())) {
            throw new BusinessException("请先禁用后再删除");
        }
        return shopRoleMapper.deleteById(id) > 0;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Boolean modifyRolePermissionByRoleId(RolePermissionParam param) {
        if (RoleConstant.ADMINISTRATOR.equals(getBean().queryById(param.getRoleId()).getCode())) {
            throw new BusinessException("超级管理员不允许修改权限");
        }
        shopRolePermissionMapper.delete(new LambdaUpdateWrapper<>(ShopRolePermissionDO.class).eq(ShopRolePermissionDO::getRoleId, param.getRoleId()));
        if (null == param.getPermissionIds() || 0 == param.getPermissionIds().length) {
            return true;
        }
        //新增关系
        List<ShopRolePermissionDO> saves = new ArrayList<>();
        for (Long permissionId : param.getPermissionIds()) {
            ShopRolePermissionDO rolePermissionDO = new ShopRolePermissionDO();
            rolePermissionDO.setRoleId(param.getRoleId());
            rolePermissionDO.setPermissionId(permissionId);

            saves.add(rolePermissionDO);
        }
        shopRolePermissionMapper.insertBatchSomeColumn(saves);
        return true;
    }

    @Override
    public List<String> queryPermissionIdsByRoleId(Long roleId) {
        if (RoleConstant.ADMINISTRATOR.equals(getBean().queryById(roleId).getCode())) {
            //超级管理员，查询全部权限
            List<ShopRoleBO> shopRoleBos = queryAll();
            if (Collections3.isEmpty(shopRoleBos)) {
                return Collections3.emptyList();
            }
            return shopRoleBos.parallelStream().map(permissionBO -> String.valueOf(permissionBO.getId())).distinct().collect(Collectors.toList());
        } else {

            List<ShopRolePermissionDO> originalRolePermissionDos = shopRolePermissionMapper.selectList(new LambdaQueryWrapper<>(ShopRolePermissionDO.class).eq(ShopRolePermissionDO::getRoleId, roleId));
            if (Collections3.isEmpty(originalRolePermissionDos)) {
                return Collections3.emptyList();
            }
            return originalRolePermissionDos.parallelStream().map(rolePermission -> String.valueOf(rolePermission.getPermissionId())).distinct().collect(Collectors.toList());
        }
    }

    @Override
    public List<ShopRoleBO> queryAll() {
        List<ShopPermissionDO> shopPermissionDos = shopPermissionMapper.selectList(Wrappers.emptyWrapper());
        return JsonUtils.jsonToList(shopPermissionDos, ShopRoleBO.class);
    }

    private static IShopRoleService getBean() {
        return SpringBeanUtil.getBean(IShopRoleService.class);
    }

    private Boolean checkUnique(ShopRoleDO roleDO) {
        Integer count = shopRoleMapper.selectCount(new LambdaQueryWrapper<>(ShopRoleDO.class)
                .ne(null != roleDO.getId(), ShopRoleDO::getId, roleDO.getId())
                .and(
                        Wrapper -> Wrapper
                                /*.eq(StringUtils.isNotBlank(roleDO.getCode()), ShopRoleDO::getCode, roleDO.getCode())
                                .or()*/
                                .eq(StringUtils.isNotBlank(roleDO.getName()), ShopRoleDO::getName, roleDO.getName())
                )
        );
        return 0 == count;
    }
}
